package com.yitao.cms.service.order;

import com.google.common.collect.Lists;
import com.skipper.base.bean.DataOutput;
import com.skipper.base.bean.PagedInput;
import com.skipper.base.bean.PagedOutput;
import com.skipper.base.service.GenericEntityService;
import com.skipper.base.utils.DateUtil;
import com.yitao.client.constant.OrderStatusEmnu;
import com.yitao.client.constant.PayEnum;
import com.yitao.client.dto.order.MallOrderRefundDto;
import com.yitao.client.dto.pay.PayStreamDto;
import com.yitao.client.model.order.MallOrderModel;
import com.yitao.client.model.order.MallOrderRefundModel;
import com.yitao.client.model.order.QMallOrderModel;
import com.yitao.client.model.order.QMallOrderRefundModel;
import com.yitao.client.model.pay.PayStreamModel;
import com.yitao.client.model.user.QUserAddressManagementModel;
import com.yitao.cms.constant.SmsMessagesConstant;
import com.yitao.cms.constant.UserSession;
import com.yitao.cms.constant.order.OrderEnums;
import com.yitao.cms.mapper.OrderMapper;
import com.yitao.cms.model.operationUser.OperationUserCmsModel;
import com.yitao.cms.service.cashCoupons.CashCouponsService;
import com.yitao.cms.service.pay.CmsPayStreamService;
import com.yitao.cms.service.shopInfo.CmsShopInfoService;
import com.yitao.cms.service.user.appUser.AppUserService;
import com.yitao.cms.utils.BaseUtils;
import com.yitao.cms.utils.DateUtils;
import com.yitao.cms.utils.DatetimeFormat;
import com.yitao.cms.vo.CategoryVo;
import com.yitao.cms.vo.order.*;
import com.yitao.cms.vo.user.appUser.AppUserInfoDetailsVo;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import static com.skipper.base.utils.DateUtil.DATE_TIME_PATTERN;

@Service
public class CmsMallOrderRefundService extends GenericEntityService<MallOrderRefundModel, MallOrderRefundDto, QMallOrderRefundModel> {

    private BaseUtils base = BaseUtils.getInstance();

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private CmsOrderService cmsOrderService;

    @Autowired
    private CmsShopInfoService cmsShopInfoService;

    @Autowired
    private CashCouponsService cashCouponsService;

    @Autowired
    private CmsOrderDetailService cmsOrderDetailService;

    @Autowired
    private CmsMallOrderRefundImgService cmsMallOrderRefundImgService;

    @Autowired
    private AppUserService appUserService;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private CmsPayStreamService cmsPayStreamService;


    public CmsMallOrderRefundService(EntityManager entityManager) {
        super(entityManager);
    }

    /**
     * 退款订单列表展示
     *
     * @param pagedInput   分页参数
     * @param orderNo      搜索关键字
     * @param searchType   搜索类型 1:商品名 2:收件人姓名 3:收件人手机 4:订单号
     * @param refundStatus 退款状态 0:全部 -10:申请退款中 -20:退款中 -30:已退款 -40:退款失败
     * @param startTime    开始时间
     * @param endTime      结束时间
     * @return
     */
    public PagedOutput<CmsMallOrderVo> getRefundOrderList(PagedInput pagedInput, String orderNo, Integer searchType, Integer refundStatus, String startTime, String endTime, Integer payType) {
        List<CmsMallOrderVo> cmsMallOrderVos = new ArrayList<>();

        CmsMallOrderVo cmsMallOrderVo = null;
        Date startDate = null;
        OperationUserCmsModel userSession = UserSession.getUserSession(request);
        if (userSession == null) { // 未登录
            throw new RuntimeException("未登录");
        }
        if (StringUtils.isNotBlank(startTime)) {
            startDate = DateUtil.parseDate(startTime + " 00:00:00", DATE_TIME_PATTERN);
        }
        Date endDate = null;
        if (StringUtils.isNotBlank(endTime)) {
            endDate = DateUtil.parseDate(endTime + " 23:59:59", DATE_TIME_PATTERN);
        }
        Date finalEndDate = endDate;
        Date finalStartDate = startDate;

        QMallOrderModel orderModel = QMallOrderModel.mallOrderModel;
        QUserAddressManagementModel userAddressManagementModel = QUserAddressManagementModel.userAddressManagementModel;

        PagingOrderRequestVo pagingOrderRequestVo = new PagingOrderRequestVo();
        if (pagedInput != null) {
            pagingOrderRequestVo.setPageNo(pagedInput.getSize() * (pagedInput.getPage() - 1));
            pagingOrderRequestVo.setPageSize(pagedInput.getSize());
        }
        if (StringUtils.isNotBlank(orderNo) && searchType == null) {
            logger.error("查询的类型 searchType 不能为空");
            return new PagedOutput("查询的类型不能为空", pagedInput, 0, new ArrayList());
        }
        if (OrderEnums.REFUND_SEARCH_ENUM.PRODUCT_NAME.getCode().equals(searchType)) {
            // 按商品名搜索
            pagingOrderRequestVo.setProductName(orderNo.trim());
        } else if (OrderEnums.REFUND_SEARCH_ENUM.RECIPIENT_NAME.getCode().equals(searchType)) {
            // 按收件人姓名搜索
            pagingOrderRequestVo.setRecipientName(orderNo.trim());
        } else if (OrderEnums.REFUND_SEARCH_ENUM.RECIPIENTC_PHONE.getCode().equals(searchType)) {
            // 按收件人电话搜索
            pagingOrderRequestVo.setRecipientcPhone(orderNo.trim());
        } else if (OrderEnums.REFUND_SEARCH_ENUM.ORDER_CODE.getCode().equals(searchType)) {
            // 按订单号查询
            pagingOrderRequestVo.setOrderCode(orderNo.trim());
        }
        /*
        0表示全部
        如果退款状态为-10和-11 tab状态展示成 申请退款中 -10
        如果退款状态为 -15和-40 tab状态展示成 退款失败 -40
        如果退款状态为 -20和-25 tab状态展示成 退款中 -20
        如果退款状态为 -30和-35 tab状态展示成 已退款 -30
         */

        List<Integer> payTypeList = Lists.newArrayList();
        if (payType != null) {
            pagingOrderRequestVo.setPayType(payType);
            if (payType.equals(OrderEnums.PayTypeName.WECHAT.getCode())) {
                //微信
                payTypeList.add(PayEnum.PayClientShowTypeEnum.WE_CHAT.getCode());
                payTypeList.add(PayEnum.PayClientShowTypeEnum.HF_WE_CHAT.getCode());
                payTypeList.add(PayEnum.PayClientShowTypeEnum.UMF_WE_CHAT.getCode());
            } else if (payType.equals(OrderEnums.PayTypeName.BANK_CARD.getCode())) {
                payTypeList.add(PayEnum.PayClientShowTypeEnum.UNION_PAY.getCode());
                payTypeList.add(PayEnum.PayClientShowTypeEnum.UMF_CARD_PAY.getCode());
                payTypeList.add(PayEnum.PayClientShowTypeEnum.UMF_CARD_PAY.getCode());
            } else if (payType.equals(OrderEnums.PayTypeName.OFFLINE.getCode())) {
                payTypeList.add(PayEnum.PayClientShowTypeEnum.OFFLINE_PAY.getCode());
            } else {
                pagingOrderRequestVo.setPayType(null);
            }
        }
        pagingOrderRequestVo.setPayTypeList(payTypeList);
        pagingOrderRequestVo.setRefundStatus(refundStatus);
        pagingOrderRequestVo.setEndTime(endDate);
        pagingOrderRequestVo.setShopId(userSession.getShopId());
        pagingOrderRequestVo.setStartTime(startDate);
        List<MallOrderRefundModel> fetch = orderMapper.getRefundOrderList(pagingOrderRequestVo);
        pagingOrderRequestVo.setPageNo(null);
        pagingOrderRequestVo.setPageSize(null);
        List<MallOrderRefundModel> fetch2 = orderMapper.getRefundOrderList(pagingOrderRequestVo);

        PagedOutput<MallOrderRefundModel> mallOrderModelPagedOutput = new PagedOutput<MallOrderRefundModel>(pagedInput, fetch2.size(), fetch);

        if (mallOrderModelPagedOutput != null && mallOrderModelPagedOutput.getData() != null && mallOrderModelPagedOutput.getData().size() != 0) {
            List<MallOrderRefundModel> mallOrderRefundModelList = mallOrderModelPagedOutput.getData();
            for (MallOrderRefundModel mallOrderRefundModel : mallOrderRefundModelList) {
                MallOrderModel mallOrderModel = cmsOrderService.getOrderByOrderId(mallOrderRefundModel.getOrderId());
                cmsMallOrderVo = new CmsMallOrderVo();
                List<CmsMallOrderDetailVo> cmsMallOrderDetailVos = Lists.newArrayList();
                if (mallOrderModel != null) {
                    BeanUtils.copyProperties(mallOrderModel, cmsMallOrderVo);
                    List<CmsMallOrderDetailVo> mallOrderDetailDto = cmsOrderDetailService.getMallOrderDetailDto(mallOrderModel.getId());
                    // 如果用户是根据商品名搜索的吧返回的list遍历一下
                    if (searchType != null && searchType == 1 && StringUtils.isNotBlank(orderNo)) {
                        // 将符合名字的获取出来放到list的第一条
                        if (mallOrderDetailDto != null && mallOrderDetailDto.size() > 1) {
                            int temp = 0;
                            for (int i = 0; i < mallOrderDetailDto.size(); i++) {
                                if (mallOrderDetailDto.get(i).getProductName().contains(orderNo)) {
                                    temp = i;
                                    break;
                                }
                            }
                            if (temp != 0) {
                                Collections.swap(mallOrderDetailDto, 0, temp);
                            }
                        }
                    }
                    cmsMallOrderDetailVos.addAll(mallOrderDetailDto);
                    // List<CmsMallOrderVo> cmsMallOrderVoByParentOrderCode = cmsOrderService.getCmsMallOrderVoByParentOrderCode(mallOrderModel.getOrderCode());
                 /*   if (cmsMallOrderVoByParentOrderCode != null && cmsMallOrderVoByParentOrderCode.size() != 0) {
                        for (CmsMallOrderVo cmsMallOrderVo1 : cmsMallOrderVoByParentOrderCode) {
                            List<CmsMallOrderDetailVo> mallOrderDetailDto = cmsOrderDetailService.getMallOrderDetailDto(cmsMallOrderVo1.getId());
                            cmsMallOrderDetailVos.addAll(mallOrderDetailDto);
                        }
                        if (cmsMallOrderVoByParentOrderCode.get(0).getShopId() != null) {
                            ShopInfoDto shopInfoDto = cmsShopInfoService.getShopInfoById(cmsMallOrderVoByParentOrderCode.get(0).getShopId());
                            if (shopInfoDto != null) {
                                cmsMallOrderVo.setShopName(shopInfoDto.getShopName());
                            }
                        }
                    }*/
                    cmsMallOrderVo.setCmsMallOrderDetailVoList(cmsMallOrderDetailVos);
//                    if (mallOrderModel.getCreateTime() != null) {
                    // 2019.07.30由订单创建时间改为订单申请退款时间
                    cmsMallOrderVo.setCreateTime(DateUtils.getDateSecondFormat(mallOrderRefundModel.getCreateTime()));
//                    }
                }
                AppUserInfoDetailsVo appUserInfoDetailsVo = appUserService.getAppUserInfo(mallOrderModel.getBuyerUserId()).getData();
                if (appUserInfoDetailsVo != null) {
                    cmsMallOrderVo.setBuyerUserPhone(appUserInfoDetailsVo.getPhone());//电话号码
                    cmsMallOrderVo.setBuyerUserName(appUserInfoDetailsVo.getNickName());//昵称
                }

                if (mallOrderRefundModel.getRefundTime() != null) {
                    cmsMallOrderVo.setRefundTime(DateUtils.getDateSecondFormat(mallOrderRefundModel.getRefundTime()));
                }

                if (mallOrderRefundModel.getRefundStatus().equals(OrderStatusEmnu.ORDER_REFUND_ENUM.APPLYING_FOR_REFUND.getKey())) {
                    cmsMallOrderVo.setCancelOrder(SmsMessagesConstant.YesOrNoEnum.YES.getCode());
                    MallOrderModel orderByOrderCode = cmsOrderService.getOrderByOrderCode(mallOrderModel.getParentOrderCode());
                    PayStreamModel payStreamInfoByOrderId = cmsPayStreamService.getPayStreamInfoByOrderId(orderByOrderCode.getId());
                    if (payStreamInfoByOrderId != null) {
                        if (payStreamInfoByOrderId.getPayClientType().equals(PayEnum.PAY_CLIENT_TYPE.OFFLINE_PAY.getCode())) {
                            cmsMallOrderVo.setCancelOrder(2);
                        }
                    } else {
                        cmsMallOrderVo.setCancelOrder(SmsMessagesConstant.YesOrNoEnum.NO.getCode());
                    }
                } else {
                    cmsMallOrderVo.setCancelOrder(SmsMessagesConstant.YesOrNoEnum.NO.getCode());
                }
                String payTypeString = "";
                /**
                 * 支付方式
                 */
                MallOrderModel orderByOrderCode = cmsOrderService.getOrderByOrderCode(mallOrderModel.getParentOrderCode());
                PayStreamModel payStreamInfoByOrderId = cmsPayStreamService.getPayStreamInfoByOrderId(orderByOrderCode.getId());
                if (payStreamInfoByOrderId != null) {
                    if (payStreamInfoByOrderId.getPayClientType().equals(PayEnum.PayClientShowTypeEnum.WE_CHAT.getCode()) ||
                            payStreamInfoByOrderId.getPayClientType().equals(PayEnum.PayClientShowTypeEnum.HF_WE_CHAT.getCode()) ||
                            payStreamInfoByOrderId.getPayClientType().equals(PayEnum.PayClientShowTypeEnum.UMF_WE_CHAT.getCode())) {
                        payTypeString = OrderEnums.PayTypeName.WECHAT.getName();
                    } else if (payStreamInfoByOrderId.getPayClientType().equals(payTypeList.add(PayEnum.PayClientShowTypeEnum.UNION_PAY.getCode())) ||
                            payStreamInfoByOrderId.getPayClientType().equals(payTypeList.add(PayEnum.PayClientShowTypeEnum.UMF_CARD_PAY.getCode())) ||
                            payStreamInfoByOrderId.getPayClientType().equals(payTypeList.add(PayEnum.PayClientShowTypeEnum.UMF_CARD_PAY.getCode()))
                    ) {
                        payTypeString = OrderEnums.PayTypeName.BANK_CARD.getName();
                    } else {
                        payTypeString = OrderEnums.PayTypeName.OFFLINE.getName();
                    }
                }
                cmsMallOrderVo.setPayTypeString(payTypeString);
                if (mallOrderRefundModel.getRefundStatus() != null) {
                    cmsMallOrderVo.setOrderCode(mallOrderRefundModel.getOrderCode());
                    String msg = OrderStatusEmnu.REFUND_STATUS.getMsg(mallOrderModel.getRefundStatus().toString());
                    if (msg != null) {
                        cmsMallOrderVo.setOrderStatus(mallOrderRefundModel.getRefundStatus());
                        cmsMallOrderVo.setOrderStatusStr(msg);
                    }
                }
                if (mallOrderRefundModel.getId() != null) {
                    cmsMallOrderVo.setId(mallOrderRefundModel.getId());
                }
                cmsMallOrderVos.add(cmsMallOrderVo);
            }
        }
        return new PagedOutput<CmsMallOrderVo>(pagedInput, mallOrderModelPagedOutput.getTotalElements(), cmsMallOrderVos);
    }

    public DataOutput<CmsMallOrderDetailsInfoVo> getAfterSaleOrderInfo(Long afterSaleId) {
        MallOrderRefundModel mallOrderRefundModel = queryFactory.select(Q).from(Q).where(Q.id.eq(afterSaleId)).fetchOne();
        if (mallOrderRefundModel == null) {
            return base.getErrorMsg();
        }
        MallOrderModel orderByOrderId = cmsOrderService.getOrderByOrderId(mallOrderRefundModel.getOrderId());
        if (orderByOrderId != null) {
            if (orderByOrderId.getId() != null) {
                CmsMallOrderDetailsInfoVo cmsMallOrderDetailsInfoVo = cmsOrderService.getOrderInfoByOrderId(orderByOrderId.getId()).getData();
                if (cmsMallOrderDetailsInfoVo != null && cmsMallOrderDetailsInfoVo.getCmsMallOrderRefundVo() != null) {
                    CmsMallOrderRefundVo cmsMallOrderRefundVo = cmsMallOrderDetailsInfoVo.getCmsMallOrderRefundVo();
                    cmsMallOrderRefundVo.setMallOrderRefundImgDtoList(cmsMallOrderRefundImgService.getMallOrderRefundImgDtoByRefundId(afterSaleId));
                }
                return base.getSuccessMsg(cmsMallOrderDetailsInfoVo);
            }
        }
        return base.getErrorMsg();
    }

    public MallOrderRefundModel getAfterSaleByOrderCode(String orderCode) {
        return queryFactory.select(Q).from(Q).where(Q.orderCode.eq(orderCode)).fetchOne();
    }


    @Transactional
    public DataOutput<PayStreamDto> updateAfterSaleOrderSolve(Long afterSaleId, Long amount, Integer solveStatus) {
        Date date = new Date();
        OperationUserCmsModel userSession = UserSession.getUserSession(request);
        if (userSession == null) { // 未登录
            return base.getErrorMsg("未登录");
        }
        MallOrderRefundModel mallOrderRefundModel = queryFactory.select(Q).from(Q).where(Q.id.eq(afterSaleId)).fetchOne();

        MallOrderModel orderByOrderId1 = cmsOrderService.getOrderByOrderId(mallOrderRefundModel.getOrderId());  //子订单
        if (orderByOrderId1 == null) {
            return base.getErrorMsg();
        }
        MallOrderModel orderByOrderCode1 = cmsOrderService.getOrderByOrderCode(orderByOrderId1.getParentOrderCode());//父订单
        if (orderByOrderCode1 == null) {
            return base.getErrorMsg();
        }
        PayStreamModel payStreamInfoByOrderId = cmsPayStreamService.getPayStreamInfoByOrderId(orderByOrderCode1.getId());
        if (payStreamInfoByOrderId == null) {
            return base.getErrorMsg();
        }
        if (payStreamInfoByOrderId.getPayClientType().equals(PayEnum.PAY_CLIENT_TYPE.UMF_CARD_PAY.getCode()) ||
                payStreamInfoByOrderId.getPayClientType().equals(PayEnum.PAY_CLIENT_TYPE.UMF_WE_CHAT.getCode())) {
            Date startDate = DateUtil.parseDate(DateUtils.getDateFormat(date, DatetimeFormat.STANDARED_DATE_FORMAT.getFormat()) + " 23:44:00", DATE_TIME_PATTERN);//开始时间
            //联动支付  23.45 - 00.25 不支持退款 时间往前后增加一分钟
            System.out.print(startDate);
            Date endDate = DateUtil.parseDate(DateUtils.getDateFormat(DateUtils.getPastDate(-1), DatetimeFormat.STANDARED_DATE_FORMAT.getFormat()) + " 00:00:26", DATE_TIME_PATTERN); //结束时间
            System.out.println(endDate);
            if (date.getTime() < endDate.getTime() && date.getTime() > startDate.getTime()) {
                return base.getErrorMsg(" 23.45 - 00.25 不支持退款 请您熟知");
            }
        }
        if (mallOrderRefundModel == null || mallOrderRefundModel.getRefundStatus() == null || !mallOrderRefundModel.getRefundStatus().equals(OrderStatusEmnu.ORDER_REFUND_ENUM.APPLYING_FOR_REFUND.getKey())) {
            return base.getErrorMsg("此订单不能进行操作");
        }
        if (amount != null && mallOrderRefundModel.getRefundFee() < amount && !solveStatus.equals(OrderStatusEmnu.REFUND_STATUS.REFUND_REJECTED.getCode())) {
            return base.getErrorMsg("金额错误,退款金额不能超过申请金额");
        }
        mallOrderRefundModel.setRefundTime(date);
        if (mallOrderRefundModel.getRefundType().equals(OrderStatusEmnu.REFUND_TYPE.ORDINARY_REFUND.getKey())) {
            mallOrderRefundModel.setRefundStatus(solveStatus);
        } else {
            mallOrderRefundModel.setRefundStatus(OrderStatusEmnu.REFUND_STATUS.PORTION_REFUND_OF.getCode());
        }
        mallOrderRefundModel.setLastUpdateTime(date);
        if (solveStatus.equals(OrderStatusEmnu.REFUND_STATUS.REFUND_REJECTED.getCode())) {
            //不改金额
        } else {
            if (amount != null) {
                mallOrderRefundModel.setRefundFee(amount);
            }
        }
        if (solveStatus.equals(OrderEnums.RefundStatusEnums.CANCELED.getCode())) {
            solveStatus = -15;
        } else if (solveStatus.equals(OrderEnums.RefundStatusEnums.OFFLINE_REFUND.getCode())) {
        } else {
            solveStatus = -30;
        }
        mallOrderRefundModel.setRefundTime(date);
        mallOrderRefundModel.setRefundStatus(solveStatus);
        mallOrderRefundModel.setLastUpdateTime(date);
        mallOrderRefundModel.setLastUpdateBy(userSession.getId());
        repository.save(mallOrderRefundModel);
        if (solveStatus.equals(-30)) {
            return base.getSuccessMsg(cmsOrderService.updateOrderAfterSaleRefund(mallOrderRefundModel));
        } else if (solveStatus.equals(OrderEnums.RefundStatusEnums.OFFLINE_REFUND.getCode())) {
            cmsOrderService.updateRefundByOrderCode(orderByOrderId1.getId(), amount, date);
            return base.getSuccessMsg();
        } else {
            MallOrderModel orderByOrderId = cmsOrderService.getOrderByOrderId(mallOrderRefundModel.getOrderId());
            orderByOrderId.setRefundStatus(OrderStatusEmnu.REFUND_STATUS.REFUND_REJECTED.getCode());//子
            cmsOrderService.save(orderByOrderId);
            MallOrderModel orderByOrderCode = cmsOrderService.getOrderByOrderCode(orderByOrderId.getParentOrderCode());
            if (orderByOrderCode != null) {
                orderByOrderCode.setRefundStatus(OrderStatusEmnu.REFUND_STATUS.REFUND_REJECTED.getCode());
                cmsOrderService.save(orderByOrderCode);
            }
        }
        return base.getSuccessMsg();
    }

    @Transactional
    public MallOrderRefundModel save(MallOrderRefundModel mallOrderRefundModel) {
        return repository.save(mallOrderRefundModel);
    }


    public MallOrderRefundModel getMallOrderRefundModelByAfterSaleId(Long afterSaleId) {
        return queryFactory.select(Q).where(Q.id.eq(afterSaleId)).fetchOne();
    }

    public int updateRefundStatusByOrderId(Long orderId, Integer payStatus) {
        return repository.updateByWhere(Q.orderId.eq(orderId), it -> it.set(Q.refundStatus, payStatus));
    }

    public MallOrderRefundModel findOrderRefundByOrderId(Long orderId) {
        if (orderId == null) {
            return null;
        }
        return repository.findOne(Q.orderId.eq(orderId).and(Q.isDelete.eq(false)));
    }
}
